// 检查配置内容合法性功能
//

#include <iostream>
#include "str_util.h"
#include "static_reg.h"
#include <map>
#include <vector>
#include <functional>
#include <any>
#include <tuple>



#define LDEBUG(x, ...) printf(x "\n", ##__VA_ARGS__)
#define LERROR(x, ...) printf("[error] " x "\n", ##__VA_ARGS__)
//简化if语句写法,让代码简洁，一但习惯，提高编写效率和浏览代码效率。
#define L_COND(cond, ret, ...)\
	do{\
	if(!(cond)){\
	printf("[error] condition fail \[" #cond "]. ", ##__VA_ARGS__); \
	return ret;\
	}	\
	}while(0)

#define L_COND_F(cond, args...)	L_COND(cond, false, ##args)
#define L_COND_V(cond, args...)	L_COND(cond, , ##args)

class RowInfo;
//目的为了用户代码简化
struct RowInfo
{
	const std::map<std::string, int>* fieldName2Idx = nullptr;
	const std::vector<std::any>* row = nullptr;

	template<class T>
	const T* Get(const std::string& field) const
	{
		auto it = fieldName2Idx->find(field);
		if (it == fieldName2Idx->end())
		{
			return nullptr;
		}
		int idx = it->second;
		if (idx >= (int)row->size())
		{
			LERROR("idx >= row.size() field=%s %d %d", field.c_str(), idx, (int)row->size());
			return nullptr;
		}

		return std::any_cast<T>(&(*row)[idx]);
	}
};
struct Sheet 
{
	using Row = std::vector<std::any>;//每行数据 类型。 包括数组内容。 按照excel 顺序
	std::map<std::string, int> fieldName2Idx; //域名 对应 Row类型数据的索引。 包括数组内容。 域名用 item0(对应excel item1), item1  表达
	std::map<uint32, Row> id2Row; //表单具体数据
	mutable std::map<uint32, RowInfo> id2RowInfo; //查找过程生成。初始化为空

	void EachRow(std::function<void(const RowInfo& rowinfo)> fun) const;
	const RowInfo* FindRow(uint32 id) const;
};




using CheckFun = std::function<bool(const Sheet&)>;
class CheckMgr
{
	friend struct SheetParser;
	std::map<std::string, CheckFun> m_sheetname2CheckFun;
	std::map<std::string, Sheet> m_sheetname2sheet;
	
public:
	static CheckMgr& Ins()
	{
		static CheckMgr obj;
		return obj;
	}

public:
	void Reg(const std::string& sheetname, CheckFun fun)
	{
		m_sheetname2CheckFun[sheetname] = fun;
	}

	void Check();

	const Sheet* GetSheet(const std::string& name) const;

private:
	CheckMgr() = default;
	Sheet& GetSheetForWrite(const std::string & name); //获取Sheet,可以修改
};